package run.yiqi.blog.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import run.yiqi.blog.dao.AdminMenuDao;
import run.yiqi.blog.dao.EndUserDao;
import run.yiqi.blog.model.AdminMenu;
import run.yiqi.blog.model.EndUser;
import run.yiqi.blog.vo.AdminMenuVo;
import run.yiqi.util.Util;

@Slf4j
@Controller
public class AdminMenuController {
    
    @Lazy @Autowired
    private AdminMenuDao adminMenuDao;
    
    @Lazy @Autowired
    private EndUserDao endUserDao;
    
    
    /**
     * 这个函数后续考虑使用Spring JDBC直接写SQL进行优化, 也可以使用Hibernate Filter进行过滤, 也可以直接写SPQL或HQL进行查询.
     * 使用Hibernate Filter的缺点就是会产生多条SQL语句; 直接写HQL或者SQL又感觉不够优雅.
     * @return
     */
    @SneakyThrows
    @ResponseBody
    @RequestMapping(value="/api/admin/adminmenu/query/listAdminMenusByUser", method=RequestMethod.GET)
    public List<AdminMenuVo> listAdminMenusByUser() {
        
        log.info("listAdminMenusByUser....");
        List<AdminMenuVo> result = new ArrayList<AdminMenuVo>();
        Map<Long, AdminMenuVo> fathers = new HashMap<Long, AdminMenuVo>();
        
        EndUser user = endUserDao.findByUsername(Util.getCurrentUsername());
        if(user!=null) {
            Set<AdminMenu> menus = user.getMenus();
            
            menus.forEach(son->{
                //log.info(son.getTitle());
                
                AdminMenuVo mvs = new AdminMenuVo();
                mvs.setId(son.getId());
                mvs.setTitle(son.getTitle());
                mvs.setFid(son.getFather().getId());
                mvs.setFtitle(son.getFather().getTitle());
                mvs.setUrl(son.getUrl());
                
                AdminMenuVo mvf = fathers.get(son.getFather().getId());
                if(mvf == null) {
                    mvf = new AdminMenuVo();
                    mvf.setId(son.getFather().getId());
                    mvf.setTitle(son.getFather().getTitle());
                    mvf.setFid(0L);
                    mvf.setFtitle(null);
                    mvf.setUrl(son.getFather().getUrl());
                    fathers.put(mvf.getId(), mvf);
                }
                mvf.getChildren().add(mvs);
                mvf.getChildren().sort((x,y)->(int)(x.getId()-y.getId()));
                //Collections.sort(mvf.getChildren());
            });
        }
        result.addAll(fathers.values());
        result.sort((x,y)->(int)(x.getId()-y.getId()));
        //Collections.sort(result);
        
        return result;
    }

    
    
    @ResponseBody
    @RequestMapping(value="/api/admin/adminmenu/query/listAdminMenus", method=RequestMethod.GET)
    public List<AdminMenuVo> listAdminMenus() {
        log.info("listAdminMenus....");
        
        List<AdminMenuVo> result = new ArrayList<AdminMenuVo>();
        
        List<AdminMenu> topMenus = adminMenuDao.findAll(new Specification<AdminMenu>() {
            private static final long serialVersionUID = 1L;
            @Override
            public Predicate toPredicate(Root<AdminMenu> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                predicates.add(criteriaBuilder.isNull(
                        root.get("father").as(AdminMenu.class)));
                
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
            
        }, new Sort(Direction.ASC, "id"));
        
        topMenus.forEach(father->{
            AdminMenuVo mvf = new AdminMenuVo();
            mvf.setId(father.getId());
            mvf.setTitle(father.getTitle());
            mvf.setFid(0L);
            mvf.setFtitle(null);
            mvf.setUrl(father.getUrl());
            
            father.getChildren().forEach(son->{
                AdminMenuVo mvs = new AdminMenuVo();
                mvs.setId(son.getId());
                mvs.setTitle(son.getTitle());
                mvs.setFid(father.getId());
                mvs.setFtitle(father.getTitle());
                mvs.setUrl(son.getUrl());
                
                mvf.getChildren().add(mvs);
            });
            result.add(mvf);
        });
        
        return result;
    }
    
}